home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / NR4USER.C < prev    next >
C/C++ Source or Header  |  1996-09-03  |  6KB  |  253 lines

  1. /* net/rom level 4 (transport) protocol user level calls
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  */
  5.  
  6. #include "global.h"
  7. #ifdef NETROM
  8. #include "mbuf.h"
  9. #include "timer.h"
  10. #include "ax25.h"
  11. #include "netrom.h"
  12.  
  13. #if !defined(_lint)
  14. static char rcsid[] OPTIONAL = "$Id: nr4user.c,v 1.9 1996/09/04 01:34:13 root Exp root $";
  15. #endif
  16.  
  17. #undef NR4DEBUG
  18.  
  19.  
  20. /* Open a NET/ROM transport connection */
  21. struct nr4cb *
  22. open_nr4 (local, remote, mode, r_upcall, t_upcall, s_upcall, user)
  23. struct nr4_addr *local;                    /* local node address */
  24. struct nr4_addr *remote;                /* destination node address */
  25. int mode;                        /* active/passive/server */
  26. void (*r_upcall) (struct nr4cb *, int16);    /* received data upcall */
  27. void (*t_upcall) (struct nr4cb *, int16);    /* transmit upcall */
  28. void (*s_upcall) (struct nr4cb *, int, int);    /* state change upcall */
  29. int user;                        /* user linkage area */
  30. {
  31. struct nr4cb *cb;
  32. struct nr4hdr hdr;
  33. struct nr4_addr nr4tmp;
  34.  
  35.     if ((cb = new_n4circ ()) == NULLNR4CB)
  36.         return NULLNR4CB;    /* No circuits available */
  37.  
  38.     if (remote == NULLNRADDR) {
  39.         remote = &nr4tmp;
  40.         (void) setcall (remote->user, " ");
  41.         (void) setcall (remote->node, " ");
  42.     }
  43.     /* Stuff what info we can into control block */
  44.  
  45.     ASSIGN (cb->remote, *remote);
  46.     /* Save local address for connect retries */
  47.     ASSIGN (cb->local, *local);
  48.  
  49.     cb->r_upcall = r_upcall;
  50.     cb->t_upcall = t_upcall;
  51.     cb->s_upcall = s_upcall;
  52.     cb->user = user;
  53.     cb->clone = 0;
  54.  
  55.     switch (mode) {
  56.         case AX_SERVER:
  57.             cb->clone = 1;        /*lint !e616 * Note fall-thru */
  58.         case AX_PASSIVE:
  59.             cb->state = NR4STLISTEN;
  60.             return cb;
  61.         case AX_ACTIVE:
  62.         default:
  63.             break;
  64.     }
  65.     /* Format connect request header */
  66.  
  67.     hdr.opcode = NR4OPCONRQ;
  68.     hdr.u.conreq.myindex = uchar(cb->mynum);
  69.     hdr.u.conreq.myid = uchar(cb->myid);
  70.     hdr.u.conreq.window = uchar(Nr4window);
  71.     memcpy (hdr.u.conreq.user, local->user, AXALEN);
  72.  
  73.     /* If I have a unique callsign per interface, then a layer violation */
  74.     /* will be required to determine the "real" callsign for my */
  75.     /* (virtual) node.  This suggests that callsign-per-interface is not */
  76.     /* desirable, which answers *that* particular open question. */
  77.  
  78.     memcpy (hdr.u.conreq.node, local->node, AXALEN);
  79.  
  80.     /* Set and start connection retry timer */
  81.  
  82.     cb->cdtries = 1;
  83.     cb->srtt = Nr4irtt;
  84.     set_timer (&cb->tcd, 2 * cb->srtt);
  85.     cb->tcd.func = nr4cdtimeout;
  86.     cb->tcd.arg = cb;
  87.     start_timer (&cb->tcd);
  88.  
  89.     /* Send connect request packet */
  90.  
  91.     nr4sframe (remote->node, &hdr, NULLBUF);
  92.  
  93.     /* Set up initial state and signal state change */
  94.  
  95.     cb->state = NR4STDISC;
  96.     nr4state (cb, NR4STCPEND);
  97.  
  98.     /* Return control block address */
  99.  
  100.     return cb;
  101. }
  102.  
  103.  
  104. /* Send a net/rom transport data packet */
  105. /* Modified to fragment packets larger then Nr_iface->mtu
  106.  * into smaller ones. This allows NETROM to work over ax.25 connections
  107.  * with paclen < 256, WITHOUT fragmenting in the ax.25 layer (ie. v2.1)
  108.  * Thus staying compatible with Thenet, BPQ etc... - WG7J
  109.  */
  110. int
  111. send_nr4 (struct nr4cb *cb, struct mbuf *bp)
  112. {
  113. struct mbuf *bp1;
  114. int16 offset, len, size;
  115.  
  116.     if (cb == NULLNR4CB || bp == NULLBUF) {
  117.         free_p (bp);
  118.         return -1;
  119.     }
  120.     if ((len = len_p (bp)) > Nr_iface->mtu) {
  121.         offset = 0;
  122.         /* It is important that all the pushdowns be done before
  123.          * any part of the original packet is freed.
  124.          * Otherwise the pushdown might erroneously overwrite
  125.          * a part of the packet that had been duped and freed.
  126.          */
  127.         while (len != 0) {
  128.             size = min (len, Nr_iface->mtu);
  129.             (void) dup_p (&bp1, bp, offset, size);
  130.             len -= size;
  131.             offset += size;
  132.             enqueue (&cb->txq, bp1);
  133.         }
  134.         free_p (bp);
  135.     } else
  136.         enqueue (&cb->txq, bp);
  137.  
  138.     return nr4output (cb);
  139. }
  140.  
  141.  
  142. /* Receive incoming net/rom transport data */
  143. struct mbuf *
  144. recv_nr4 (struct nr4cb *cb, int16 cnt)
  145. {
  146. struct mbuf *bp;
  147.  
  148.     if (cb->rxq == NULLBUF)
  149.         return NULLBUF;
  150.  
  151.     if (cnt == 0) {
  152.         bp = cb->rxq;    /* Just give `em everything */
  153.         cb->rxq = NULLBUF;
  154.     } else {
  155.         bp = ambufw (cnt);
  156.         bp->cnt = pullup (&cb->rxq, bp->data, cnt);
  157.     }
  158.     /* If this has un-choked us, reopen the window */
  159.     if (cb->qfull && len_p (cb->rxq) < Nr4qlimit) {
  160.         cb->qfull = 0;    /* Choke flag off */
  161.         nr4ackit (cb);    /* Get things rolling again */
  162.     }
  163.     return bp;
  164. }
  165.  
  166.  
  167. /* Close a NET/ROM connection */
  168. void
  169. disc_nr4 (struct nr4cb *cb)
  170. {
  171. struct nr4hdr hdr;
  172.  
  173.     if (cb->state == NR4STLISTEN) {
  174.         free_n4circ (cb);
  175.         return;
  176.     }
  177.     if (cb->state != NR4STCON)
  178.         return;
  179.  
  180.     /* Format disconnect request packet */
  181.  
  182.     hdr.opcode = NR4OPDISRQ;
  183.     hdr.yourindex = uchar(cb->yournum);
  184.     hdr.yourid = uchar(cb->yourid);
  185.  
  186.     /* Set and start timer */
  187.  
  188.     cb->cdtries = 1;
  189.     set_timer (&cb->tcd, 2 * cb->srtt);
  190.     cb->tcd.func = nr4cdtimeout;
  191.     cb->tcd.arg = cb;
  192.     start_timer (&cb->tcd);
  193.  
  194.     /* Send packet */
  195.  
  196.     nr4sframe (cb->remote.node, &hdr, NULLBUF);
  197.  
  198.     /* Signal state change.  nr4state will take care of stopping */
  199.     /* the appropriate timers and resetting window pointers. */
  200.  
  201.     nr4state (cb, NR4STDPEND);
  202.  
  203. }
  204.  
  205.  
  206. /* Abruptly terminate a NET/ROM transport connection */
  207. void
  208. reset_nr4 (struct nr4cb *cb)
  209. {
  210.     /* Be nice and send a disconnect frame */
  211.     disc_nr4 (cb);
  212.     cb->dreason = NR4RRESET;
  213.     nr4state (cb, NR4STDISC);
  214. }
  215.  
  216.  
  217. /* Force retransmission on a NET/ROM transport connection */
  218. int
  219. kick_nr4 (struct nr4cb *cb)
  220. {
  221. unsigned seq;
  222. struct timer *t;
  223.  
  224.     if (!nr4valcb (cb))
  225.         return -1;
  226.  
  227.     switch (cb->state) {
  228.         case NR4STCPEND:
  229.         case NR4STDPEND:
  230.             stop_timer (&cb->tcd);
  231.             nr4cdtimeout (cb);
  232.             break;
  233.  
  234.         case NR4STCON:
  235.             if (cb->nextosend != cb->ackxpected) {    /* if send window is open: */
  236.                 for (seq = cb->ackxpected;
  237.                      nr4between ((unsigned) cb->ackxpected, seq, (unsigned) cb->nextosend);
  238.                      seq = (seq + 1) & NR4SEQMASK) {
  239.                     t = &cb->txbufs[seq % cb->window].tretry;
  240.                     stop_timer (t);
  241.                     t->state = TIMER_EXPIRE;    /* fool retry routine */
  242.                 }
  243.                 nr4txtimeout (cb);
  244.             }
  245.             break;
  246.         default:
  247.             break;
  248.     }
  249.     return 0;
  250. }
  251.  
  252. #endif /* NETROM */
  253.